/*
 *    Copyright 2022 The DSMS Authors.
 *
 *    Licensed under the Apache License, Version 2.0 (the "License");
 *    you may not use this file except in compliance with the License.
 *    You may obtain a copy of the License at
 *
 *        http://www.apache.org/licenses/LICENSE-2.0
 *
 *    Unless required by applicable law or agreed to in writing, software
 *    distributed under the License is distributed on an "AS IS" BASIS,
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *    See the License for the specific language governing permissions and
 *    limitations under the License.
 */

package com.dsms.modules.sms.service.impl;


import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.dsms.common.constant.AlertAppriseTypeEnum;
import com.dsms.common.constant.AlertMessageAppriseStatusEnum;
import com.dsms.modules.alert.entity.AlertApprise;
import com.dsms.modules.alert.entity.AlertContact;
import com.dsms.modules.alert.entity.AlertMessage;
import com.dsms.modules.alert.service.IAlertAppriseService;
import com.dsms.modules.alert.service.IAlertMessageService;
import com.dsms.modules.alert.service.IAlertNotifyHandler;
import com.dsms.modules.sms.SmsClient;
import com.dsms.modules.sms.SmsClientFactory;
import com.dsms.modules.sms.model.SmsSendMessage;
import com.dsms.modules.sms.model.convert.SmsMessageConvert;
import com.dsms.modules.sms.service.ISmsSendService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * Sms service implement
 */
@Service
@Slf4j
public class SmsSendServiceImpl implements ISmsSendService, IAlertNotifyHandler {

    @Resource
    private SmsClientFactory smsClientFactory;

    @Autowired
    private IAlertAppriseService alertAppriseService;

    @Autowired
    private IAlertMessageService alertMessageService;


    @Override
    @EventListener(ApplicationReadyEvent.class)
    public void initSmsClient() {
        LambdaQueryWrapper<AlertApprise> alertAppriseQuery = Wrappers.lambdaQuery(AlertApprise.class).eq(AlertApprise::getType, AlertAppriseTypeEnum.SMS.getCode());
        List<AlertApprise> alertApprises = alertAppriseService.list(alertAppriseQuery);
        if (!alertApprises.isEmpty()) {
            log.info("init sms provider client...");
            for (AlertApprise alertApprise : alertApprises) {
                smsClientFactory.createOrUpdateSmsClient(alertApprise);
            }
        }
    }

    @Override
    public void doSendSms(SmsSendMessage message) {
        // get sms provider client
        SmsClient smsClient = smsClientFactory.getSmsClient(message.getSmsProvider());
        // send sms
        smsClient.sendSms(UUID.randomUUID().toString(), message.getMobiles(), message.getSmsSignName(), message.getSmsTemplate(), message.getTemplateParams());
    }


    @Override
    public Integer getType() {
        return AlertAppriseTypeEnum.SMS.getCode();
    }

    @Override
    public void sendAlertMessage(AlertApprise apprise, String alertMessage) {
        List<String> contacts = apprise.getContacts().stream().map(AlertContact::getContactAccount).collect(Collectors.toList());
        SmsSendMessage smsSendMessage = SmsMessageConvert.convert(apprise, contacts);
        doSendSms(smsSendMessage);
    }

    @Override
    public void updateAlertMessageAppriseStatus(AlertMessage alertMessage, boolean isSuccess) {
        //update status only if successfully sent
        if (isSuccess) {
            alertMessage.setSmsStatus(AlertMessageAppriseStatusEnum.UP_AND_APPRISED.getCode());
            LambdaUpdateWrapper<AlertMessage> updateWrapper = new LambdaUpdateWrapper<>();
            updateWrapper.eq(AlertMessage::getId, alertMessage.getId()).set(AlertMessage::getSmsStatus, alertMessage.getSmsStatus());
            alertMessageService.update(updateWrapper);
        }
    }
}
